package com.legal.app.service.impl;

/**
 * @author Ale
 * @description
 * @date 2025/6/18 9:25
 */

import com.alibaba.fastjson2.JSONObject;
import com.legal.app.domain.User;
import com.legal.app.domain.WechatUserInfo;
import com.legal.app.domain.dto.LoginResultDTO;
import com.legal.app.mapper.UserMapper;
import com.legal.app.service.WechatAuthService;

import com.legal.app.config.WechatOpenConfig;
import com.legal.common.core.domain.entity.SysUser;
import com.legal.common.core.domain.model.LoginUser;
import com.legal.common.core.redis.RedisCache;
import com.legal.common.utils.DateUtils;
import com.legal.framework.web.service.TokenService;
import com.legal.system.service.impl.SysUserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.concurrent.TimeUnit;

import static com.legal.framework.datasource.DynamicDataSourceContextHolder.log;

/**
 * 微信认证服务实现
 */
@Service
public class WechatAuthServiceImpl implements WechatAuthService {
    @Autowired
    private WechatOpenConfig config;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private SysUserServiceImpl sysUserService;

    @PostConstruct
    public void validateConfig() {
        String appId = config.getAppId();
        String appSecret = config.getAppSecret();
        if (appId == null || appId.length() != 18) {
            throw new IllegalStateException("微信AppID配置错误，长度必须为18位");
        }
        if (appSecret == null || appSecret.length() != 32) {
            throw new IllegalStateException("微信AppSecret配置错误，长度必须为32位");
        }
    }

    @Override
    public String getAuthorizationUrl(String state) {
        return String.format(
                "%s?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect",
                config.getAuthUrl(),
                config.getAppId(),
                config.getRedirectUri(),
                config.getScope(),
                state
        );
    }

    /**
     * 调用微信接口获取 openid 和 session_key
     */
    private JSONObject getWechatSession(String code) throws UnsupportedEncodingException {
        // 拼接请求 URL
        String url = "https://api.weixin.qq.com/sns/jscode2session" +
                "?appid=" + URLEncoder.encode(config.getAppId(), "UTF-8") +
                "&secret=" + URLEncoder.encode(config.getAppSecret(), "UTF-8") +
                "&js_code=" + URLEncoder.encode(code, "UTF-8") +
                "&grant_type=authorization_code";

        // 记录日志
        log.error("【微信登录】URL: [{}]", url);

        // 发起 HTTP 请求
        String result = restTemplate.getForObject(url, String.class);

        // 解析返回结果
        JSONObject json = JSONObject.parseObject(result);

        // 检查错误码
        if (json.containsKey("errcode")) {
            throw new RuntimeException("微信登录失败: " + json.getString("errmsg"));
        }

        // 记录日志
        log.error("【微信登录】OpenID: [{}], SessionKey: [{}]",
                json.getString("openid"),
                json.getString("session_key"));

        return json;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Object wechatLogin(String code, String encryptedData, String iv) throws Exception {
        // 1. 一次请求获取 openid 和 session_key
        JSONObject weChatResult = getWechatSession(code);
        String openId = weChatResult.getString("openid");
        String sessionKey = weChatResult.getString("session_key");
        System.out.println("openId:" + openId);
        System.out.println("sessionKey已缓存:" + sessionKey);

        cacheSessionKey(openId, sessionKey); // 缓存 session_key
        WechatUserInfo wechatUser = decryptUserInfo(encryptedData, iv, sessionKey); // 解密用户信息
        System.out.println("wechatUser:" + wechatUser);

        // 2. 查询用户
        User user = userMapper.selectByWechatOpenid(openId);
        System.out.println("user:" + user);
        LoginResultDTO result = new LoginResultDTO();

        // 3. 处理用户注册
        if (user == null) {
            user = registerNewUser(openId, wechatUser);
            SysUser sysUser = sysUserService.selectUserById(user.getId());
            result = createLoginResultDTO(user, createLoginUser(user, sysUser));
            return result;
        }

        // 4. 处理用户登录
        SysUser sysUser = sysUserService.selectUserById(user.getId());
        LoginUser loginUser = createLoginUser(user, sysUser);
        result = createLoginResultDTO(user, loginUser);
        return result;
    }

//    @Override
//    public String getOpenid(String code) throws UnsupportedEncodingException {
//        String url = "https://api.weixin.qq.com/sns/jscode2session" +
//                "?appid=" + URLEncoder.encode(config.getAppId(), "UTF-8") +
//                "&secret=" + URLEncoder.encode(config.getAppSecret(), "UTF-8") +
//                "&js_code=" + URLEncoder.encode(code, "UTF-8") +
//                "&grant_type=authorization_code";
//        log.error("【微信登录】URL: [{}]", url);
//        String result = restTemplate.getForObject(url, String.class);
//        JSONObject json = JSONObject.parseObject(result);
//        if (json.containsKey("errcode")) {
//            throw new RuntimeException("微信登录失败: " + json.getString("errmsg"));
//        }
//        log.error("【微信登录】OpenID: [{}]", json.getString("openid"));
//        return json.getString("openid");
//    }

//    private String getSessionKeyFromResult(String code) throws UnsupportedEncodingException {
//        String url = "https://api.weixin.qq.com/sns/jscode2session" +
//                "?appid=" + URLEncoder.encode(config.getAppId(), "UTF-8") +
//                "&secret=" + URLEncoder.encode(config.getAppSecret(), "UTF-8") +
//                "&js_code=" + URLEncoder.encode(code, "UTF-8") +
//                "&grant_type=authorization_code";
//        String result = restTemplate.getForObject(url, String.class);
//        JSONObject json = JSONObject.parseObject(result);
//        if (json.containsKey("errcode")) {
//            throw new RuntimeException("获取session_key失败: " + json.getString("errmsg"));
//        }
//        return json.getString("session_key");
//    }

    private void cacheSessionKey(String openId, String sessionKey) {
        redisCache.setCacheObject("wechat_session:" + openId, sessionKey, 7200, TimeUnit.SECONDS);
    }

    public WechatUserInfo decryptUserInfo(String encryptedData, String iv, String sessionKey) {
        try {
            byte[] dataByte = Base64.getDecoder().decode(encryptedData);
            byte[] keyByte = Base64.getDecoder().decode(sessionKey);
            byte[] ivByte = Base64.getDecoder().decode(iv);

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(ivByte);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

            byte[] decrypted = cipher.doFinal(dataByte);
            String decryptedData = new String(decrypted, StandardCharsets.UTF_8);
            JSONObject jsonObject = JSONObject.parseObject(decryptedData);

            WechatUserInfo userInfo = new WechatUserInfo();
            userInfo.setOpenid(jsonObject.getString("openId"));
            userInfo.setNickname(jsonObject.getString("nickName"));
            userInfo.setGender(jsonObject.getInteger("gender"));
            userInfo.setAvatarUrl(jsonObject.getString("avatarUrl"));
            return userInfo;
        } catch (Exception e) {
            throw new RuntimeException("解密用户信息失败", e);
        }
    }

    private User registerNewUser(String openId, WechatUserInfo wechatUser) {

        SysUser sysUser = new SysUser();
        //微信登录注册时候默认用户名为id
        sysUser.setUserName(wechatUser.getOpenid());
        sysUser.setNickName(wechatUser.getNickname());
        sysUser.setStatus("0");
        sysUser.setCreateTime(DateUtils.getNowDate());
        //默认密码123456
        sysUser.setPassword(new BCryptPasswordEncoder().encode("123456"));
        sysUserService.insertUser(sysUser);
        //默认分配角色为小程序用户
        userMapper.insertSysUserRole(sysUser.getUserId(), 3L);


        User user = new User();
        SysUser newSysUser = userMapper.selectSysUserByUsername(openId);
        String userId = sysUser.getUserId().toString();
        //确保注册时候的用户id与系统用户id一致
        user.setId(Long.parseLong(userId));
        user.setWechatOpenid(wechatUser.getOpenid());
//        user.setPhoneNumber("11111111111");
        user.setNickName(wechatUser.getNickname());
        user.setAvatarUrl(wechatUser.getAvatarUrl());
//        user.setEncodeCipher(new BCryptPasswordEncoder().encode("123456"));
        user.setStatus(1L);
        user.setCreateTime(DateUtils.getNowDate());
        user.setUserType(1L);
        userMapper.insert(user);

        return user;
    }

    private LoginUser createLoginUser(User user, SysUser sysUser) {
        LoginUser loginUser = new LoginUser();
        loginUser.setUser(sysUser);
        loginUser.setUserId(user.getId());
        loginUser.setUsername(sysUser.getUserName());
        String token = tokenService.createToken(loginUser);
        loginUser.setToken(token);
        redisCache.setCacheObject("token:" + token, loginUser, 3600, TimeUnit.SECONDS);
        return loginUser;
    }

    private LoginResultDTO createLoginResultDTO(User user, LoginUser loginUser) {
        LoginResultDTO result = new LoginResultDTO();
        result.setUserId(user.getId());
        result.setNickName(user.getNickName());
        result.setAvatarUrl(user.getAvatarUrl());
        result.setUserType(user.getUserType());
        result.setToken(loginUser.getToken());
        result.setExpireTime(loginUser.getExpireTime());
        return result;
    }


    //取消默认手机号和密码，需要后面绑定手机号
}
